package lims.bridge.remoteprint;


import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.util.HashMap;
import java.util.Map;
import java.util.Properties;

import lims.client.DeviceTableModel;
import lims.client.LimsService;
import lims.client.MainFrame;
import lims.tools.DES;

import org.apache.commons.lang.StringUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.io.support.PropertiesLoaderUtils;


@Configuration
@ComponentScan
public class Main{
	
	private static Log logger=LogFactory.getLog(Main.class);
	public static ApplicationContext applicationContext;
	public static RemotePrintBridge bridgeThread;
	public static String defaultConfigName="variables.properties";
	public static Properties defaultVariables;
	public static String DESPwd="bsl";
	public static Map<String,Object> userVariables=new HashMap<>();
	
	@Bean
	@Autowired
	public LimsService initializeLimsService(){
		LimsService service=new LimsService();
		service.setLoginURL(defaultVariables.getProperty("login_url"));
		service.setHttpCheckURL(defaultVariables.getProperty("http_check_url"));
		service.setLogAppendURL(defaultVariables.getProperty("log_append_url"));

		service.setServerURL((String) userVariables.get("data_url"));

		service.setServiceName((String) userVariables.get("bridge_id"));		
		
		if(defaultVariables.get("uid_field_name")!=null)service.setUidFieldName((String) defaultVariables.get("uid_field_name"));
		if(defaultVariables.get("pwd_field_name")!=null)service.setPwdFieldName((String) defaultVariables.get("pwd_field_name"));
		
		service.setUid((String) userVariables.get("data_uid"));
		service.setPwd((char[]) userVariables.get("data_pwd"));		
		
		service.setAuthUser((String) userVariables.get("auth_uid"));
		if(userVariables.get("auth_pwd")!=null)
		service.setAuthPassword(new String((char[]) userVariables.get("auth_pwd")));		
		service.start();
		return service;
	}
	
	@Bean
	@Autowired
	protected RemotePrintBridgeService initRemotePrintBridgeService(LimsService service){
		RemotePrintBridgeService bridgeService=new RemotePrintBridgeService();
		bridgeService.setLimsService(service);
		bridgeService.setServerAddress((String) userVariables.get("bridge_address"));
		bridgeService.setBridgeId((String) userVariables.get("bridge_id"));	
		bridgeService.setUid((String) userVariables.get("bridge_username"));
		bridgeService.setPassword(new String((char[]) userVariables.get("bridge_password")));
		
		return bridgeService;
	}
		
	
	public static void readUserConfig(String fileName) throws Exception{
		ObjectInputStream ois=new ObjectInputStream(new FileInputStream(fileName));
		userVariables.put("data_url",ois.readUTF());
		userVariables.put("data_uid",ois.readUTF());
		userVariables.put("data_pwd",readPassword(ois));

		userVariables.put("auth_uid",StringUtils.trimToNull(ois.readUTF()));
		userVariables.put("auth_pwd",readPassword(ois));

		
		userVariables.put("bridge_address",ois.readUTF());
		userVariables.put("bridge_username",ois.readUTF());
		userVariables.put("bridge_password",readPassword(ois));
		
		userVariables.put("bridge_id",ois.readUTF());
					
		DeviceTableModel tmp=(DeviceTableModel) ois.readObject();
		DeviceTableModel model=DeviceTableModel.getInstance();
		model.clear();
		model.addAll(tmp);		
		ois.close();
	}
	
	private static char[] readPassword(ObjectInputStream ois) throws Exception{
		int l=ois.readInt();
		if(l<0) throw new Exception("password length error");
		if(l==0) return null;
		byte[] encoded=new byte[l];
		ois.read(encoded,0,l);
		String tmp=new String(DES.decrypt(encoded,"boshland".getBytes("utf8")),"utf8");		
		return tmp.toCharArray();
	}
	private static void writePassword(ObjectOutputStream oos,char[] pwd) throws Exception{
		String tmp=new String(pwd);
		byte[] encoded=DES.encrypt(tmp.getBytes("utf8"),"boshland".getBytes("utf8"));
		if(encoded==null){
			oos.writeInt(0);
		}else{
			oos.writeInt(encoded.length);
			oos.write(encoded);
		}
	}
	
	public static void writeUserConfig() throws Exception{
		String userConfigFileName=defaultVariables.getProperty("config_file_name","conf/userdata.dat");
		writeUserConfig(userConfigFileName);
	}
	
	public static void writeUserConfig(String fileName) throws Exception{
		ObjectOutputStream oos=new ObjectOutputStream(new FileOutputStream(fileName));
		try{
			if(userVariables.get("data_url")==null) throw new Exception("数据服务器未设置");
			if(userVariables.get("data_uid")==null) throw new Exception("数据服务器登录用户未设置");
			if(userVariables.get("data_pwd")==null) throw new Exception("数据服务器登录密码未设置");
	
			if(userVariables.get("bridge_address")==null) throw new Exception("通讯服务器未设置");
			if(userVariables.get("bridge_username")==null) throw new Exception("通讯服务用户未设置");
			if(userVariables.get("bridge_password")==null) throw new Exception("通讯服务密码未设置");
			
			if(userVariables.get("bridge_id")==null) throw new Exception("桥名称未设置");
			
			oos.writeUTF((String) userVariables.get("data_url"));
			oos.writeUTF((String) userVariables.get("data_uid"));
			writePassword(oos,(char[]) userVariables.get("data_pwd"));
	
			oos.writeUTF(StringUtils.trimToEmpty((String)userVariables.get("auth_uid")));
			writePassword(oos,(char[]) userVariables.get("auth_pwd"));
	
	
			oos.writeUTF((String) userVariables.get("bridge_address"));
			oos.writeUTF((String) userVariables.get("bridge_username"));
			writePassword(oos,(char[]) userVariables.get("bridge_password"));
			oos.writeUTF((String) userVariables.get("bridge_id"));
			
			oos.writeObject(DeviceTableModel.getInstance());
			oos.flush();
		}finally{
			oos.close();
		}
	}
	
	public static void main(String[] args) throws Exception {
		defaultVariables=PropertiesLoaderUtils.loadAllProperties(defaultConfigName);
		String userConfigFileName=defaultVariables.getProperty("config_file_name","conf/userdata.dat");
		boolean loaded=false;
		try{
			readUserConfig(userConfigFileName);
			loaded=true;
		}catch(Exception e){
			
		}
		
		String mode="help";
		if(args.length>0) mode=args[0];
		logger.info("main args0 ".concat(mode));
		if(mode.equalsIgnoreCase("start")){
			if(!loaded)throw new Exception("配置文件不正确");
			logger.info("service starting");		
			AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(Main.class);
//			LimsService limsService=(LimsService) context.getBean(LimsService.class);
			RemotePrintBridgeService bridgeService=(RemotePrintBridgeService) context.getBean(RemotePrintBridgeService.class);			
			bridgeThread=new RemotePrintBridge(bridgeService);
			bridgeThread.start();
			logger.info("work thread start successfull");		
			bridgeThread.join();
			context.close();
			logger.info("service work finished");		
		}else if(mode.equalsIgnoreCase("stop")){
			logger.info("service stopping");		
			bridgeThread.setStop();
			bridgeThread.join(10000);
			logger.info("service stop successfull");
		}else if(mode.equalsIgnoreCase("config")){
			MainFrame mainFrame=new MainFrame();					
			LimsService limsService=new Main().initializeLimsService();
			mainFrame.setLimsService(limsService);
			mainFrame.setVisible(true);
		}else{
			System.out.println("Usage: java -jar xxx.jar start/stop/config/help");
		}
	}
	
	
}
